Skip to content

fix(core): split client/server tsdown builds to keep ws/node out of browser#347

Merged
antfu merged 2 commits into
mainfrom
antfu/moscow
May 15, 2026
Merged

fix(core): split client/server tsdown builds to keep ws/node out of browser#347
antfu merged 2 commits into
mainfrom
antfu/moscow

Conversation

@antfu
Copy link
Copy Markdown
Member

@antfu antfu commented May 14, 2026

Description

In 0.1.23, the browser-side dock crashes with SyntaxError: ... does not provide an export named 'WebSocketServer': rolldown's automatic chunking hoisted the __exportAll runtime helper into a chunk that also reached devframe/rpc/transports/ws-server, so the client DockStandalone-*.js statically pulled in ws (which Vite resolves to ws/browser.js, a module that has no WebSocketServer export). Split packages/core/tsdown.config.ts into two configs (client + server) inside one defineConfig([...]) so the chunk graphs are independent — server modules structurally cannot leak into the client output. Also added a build:check script (packages/core/scripts/check-client-dist.ts) that BFS-walks every chunk reachable from dist/client/inject.js and dist/client/webcomponents.js (following both static and dynamic imports) and fails the build on any forbidden static import (ws, h3, node:*, devframe/rpc/transports/*, devframe/node*), wired into the existing build step so it gates prepack.

Linked Issues

Additional context

Verified via full pnpm build (turbo, 5 packages), the new guard (scans 8 chunks, all clean), manual greps on dist/client/ (no ws/h3/node:/ws-server matches), and pnpm test / pnpm typecheck / pnpm lint — all green. The export * cleanup in webcomponents/index.ts is intentionally deferred since it's no longer load-bearing now that the builds are isolated.

…of the browser bundle

Rolldown's automatic chunking was hoisting the `__exportAll` runtime helper
into a chunk that also reached `devframe/rpc/transports/ws-server`, so
client `DockStandalone-*.js` statically imported `ws` and threw
`SyntaxError: ... does not provide an export named 'WebSocketServer'` in
the browser. Split `packages/core/tsdown.config.ts` into two configs (client
+ server) so the chunk graphs are independent, and add a `build:check`
guard that BFS-walks `dist/client/*.js` and fails on any forbidden static
import (`ws`, `h3`, `node:*`, `devframe/rpc/transports/*`, `devframe/node*`).
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 14, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@vitejs/devtools@347
npm i https://pkg.pr.new/@vitejs/devtools-kit@347
npm i https://pkg.pr.new/@vitejs/devtools-rolldown@347
npm i https://pkg.pr.new/@vitejs/devtools-self-inspect@347

commit: e3159d2

Move the forbidden-import check out of the `build:check` npm script and
into the client config's `build:done` hook, so it runs automatically as
part of the tsdown build (including `watch` mode) without needing a
separate pipeline step. The script becomes an exported `checkClientDist`
function that throws on violation; `package.json` drops the `build:check`
entry.
@antfu antfu merged commit 3085997 into main May 15, 2026
10 checks passed
@antfu antfu deleted the antfu/moscow branch May 15, 2026 01:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant